// File provided for Microsoft Shared Source.
// Copyright (c) Microsoft Corporation. All rights reserved.

#pragma once
#include "resource.h"       // main symbols

#include "WMIFldr.h"
#include <shidfact.h>

typedef SHCOLUMNID PROPERTYKEY;

struct COLUMNINFO
{
    DWORD lvcfmt;
    DWORD cxChar;
    DWORD dwResId;
    DWORD shcolstatef;

    PROPERTYKEY pkey;
};

enum WMIObjectType
{
    WMIOT_Invalid      = 0,
    WMIOT_Namespace    = 1,
    WMIOT_Class        = 2,
    WMIOT_Instance     = 3,
    WMIOT_Property     = 4,
};

struct WMIINFO
{
    WMIObjectType eObjType;
    DWORD sfgaof;
};

// CWMIFldr
class CWMIFldr:
    public IShellFolder2,
    public IClassFactory,
    public IPersistFolder2,
    public IPersistIDList,
    public CItemIDFactory<WMIINFO, 0x45879625>
{
    LONG _cRef;
    PIDLIST_ABSOLUTE _pidl;

    static const COLUMNINFO s_rgColumns[];

    ~CWMIFldr();

    static HRESULT s_GetObjectForIDList(PCUITEMID_CHILD pidl, const WMIINFO **ppWMIInfo, IWbemClassObject **ppObj);
    static HRESULT s_GetObjectForParsingPath(PCWSTR pszParsingPath, IWbemClassObject **ppObj);
    static HRESULT s_GetStringProperty(IWbemClassObject *pObj, PCWSTR pszPropertyName, VARIANT *pv);
    static HRESULT s_GetStringProperty(IWbemClassObject *pObj, PCWSTR pszPropertyName, PROPVARIANT *ppropvar);

    static HRESULT s_TraceIDList(PCUIDLIST_RELATIVE pidl);
    static HRESULT s_TraceIDList(PCUITEMID_CHILD pidl);

    HRESULT _CreateFolder(PCUITEMID_CHILD pidlChild, REFIID riid, __deref_out void **ppv);
    
    HRESULT _GetRelativeDisplayName(PCUITEMID_CHILD pidl, PWSTR *ppsz);
    HRESULT _GetAbsoluteDisplayName(PCUITEMID_CHILD pidl, PWSTR *ppsz);
    HRESULT _GetAbsoluteParsingName(PCUITEMID_CHILD pidl, PWSTR *ppsz);
    HRESULT _GetRelativeParsingName(PCUITEMID_CHILD pidl, PWSTR *ppsz);

    HRESULT _CompareProperties(PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2, const PROPERTYKEY &pkey);
    HRESULT _CompareRelativeIDLists(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2);

    HRESULT _GetChildCount(PCUITEMID_CHILD pidl, VARIANT *pv);
public:
    CWMIFldr();

    DECLARE_REGISTRY_RESOURCEID(IDR_CWMIFLDR)

    // IUnknown
    IFACEMETHODIMP QueryInterface(REFIID, void **ppv);
    IFACEMETHODIMP_(ULONG) AddRef()
    {
        return InterlockedIncrement(&_cRef);
    }
    IFACEMETHODIMP_(ULONG) Release()
    {
        LONG cRef = InterlockedDecrement(&_cRef);
        if (0 == cRef)
        {
            delete this;
        }
        return cRef;
    }

    // IClassFactory
    IFACEMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv);
    IFACEMETHODIMP LockServer(BOOL fLock);

    // IPersistFolder2
    IFACEMETHODIMP Initialize(PCUIDLIST_ABSOLUTE pidl);
    IFACEMETHODIMP GetClassID(CLSID *pClassID);
    IFACEMETHODIMP GetCurFolder(PIDLIST_ABSOLUTE *ppidl);

    // IShellFolder
    IFACEMETHODIMP ParseDisplayName(HWND hwnd, LPBC pbc, LPOLESTR pszDisplayName, ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes);
    IFACEMETHODIMP EnumObjects(HWND hwnd, SHCONTF grfFlags, IEnumIDList **ppenumIDList);
    IFACEMETHODIMP BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbc, REFIID riid, void **ppv);
    IFACEMETHODIMP BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbc, REFIID riid, void **ppv);
    IFACEMETHODIMP CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2);
    IFACEMETHODIMP CreateViewObject(HWND hwndOwner, REFIID riid, void **ppv);
    IFACEMETHODIMP GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, SFGAOF *rgfInOut);
    IFACEMETHODIMP GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT *rgfReserved, void **ppv);
    IFACEMETHODIMP GetDisplayNameOf(PCUITEMID_CHILD pidl, SHGDNF uFlags, STRRET *pName);
    IFACEMETHODIMP SetNameOf(HWND hwnd, PCUITEMID_CHILD pidl, LPCOLESTR pszName, SHGDNF uFlags, PITEMID_CHILD *ppidlOut);

    // IShellFolder2
    IFACEMETHODIMP EnumSearches(IEnumExtraSearch **ppEnum);
    IFACEMETHODIMP GetDefaultColumn(DWORD dwReserved, ULONG *pSort, ULONG *pDisplay);
    IFACEMETHODIMP GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *pcsFlags);
    IFACEMETHODIMP GetDefaultSearchGUID(GUID *pguid);
    IFACEMETHODIMP GetDetailsEx(PCUITEMID_CHILD pidl, const PROPERTYKEY *pscid, VARIANT *pv);
    IFACEMETHODIMP GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd);
    IFACEMETHODIMP MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid);

    // IPersistIDList
    IFACEMETHODIMP GetIDList(PIDLIST_ABSOLUTE *ppidl);
    IFACEMETHODIMP SetIDList(PCIDLIST_ABSOLUTE pidl);

    static HRESULT s_GetServer(__in_opt PCWSTR pszComputer, __in_opt PCWSTR pszNamespace, __deref_out IWbemServices **ppWbemServices);
    static HRESULT s_CreateIDList(__in IWbemClassObject *pObj, __deref_out PITEMID_CHILD *pidlChild);
    static HRESULT s_CreateIDList(__in IWbemClassObject *pInstance, PCWSTR pszPropertyName, __deref_out PITEMID_CHILD *pidlChild);
};
